package com.guyu.common.web.interceptor;

import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.guyu.common.web.config.properties.GuyuWebProperties;
import com.guyu.common.web.util.GuyuServletUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StopWatch;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import java.util.Map;

/**
 * Web请求日志拦截器
 * 打印请求参数、响应结果和耗时
 */
@Slf4j(topic = "request")
public class RequestLogInterceptor implements HandlerInterceptor {
    private final static ThreadLocal<StopWatch> KEY_CACHE = new ThreadLocal<>();
    private final GuyuWebProperties webProperties;

    public RequestLogInterceptor(GuyuWebProperties webProperties) {
        this.webProperties = webProperties;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (!hasEnabled(request)) {
            return true;
        }
        //计算耗时
        StopWatch stopWatch = new StopWatch();
        KEY_CACHE.set(stopWatch);
        stopWatch.start();
        //请求地址
        String url = request.getMethod() + " " + request.getRequestURI();
        // headers
        JSONObject headerMap = new JSONObject();
        webProperties.getRequestLog().getHeaders().forEach(header -> {
            headerMap.put(header, request.getHeader(header));
        });
        log.info("[GUYU] begin => url:[ {} ], header:[ {} ]", url, headerMap.toJSONString());
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        if (!hasEnabled(request)) {
            return;
        }
        StopWatch stopWatch = KEY_CACHE.get();
        stopWatch.stop();
        //耗时
        long cost = stopWatch.getTotalTimeMillis();
        //请求地址
        String url = request.getMethod() + " " + request.getRequestURI();

        //处理GET或表单POST参数
        String reqParam = "";
        Map<String, String[]> parameterMap = request.getParameterMap();
        if (MapUtil.isNotEmpty(parameterMap)) {
            reqParam = JSON.toJSONString(parameterMap);
        }
        //是否打印请求参数
        String reqBody = "";
        if (webProperties.getRequestLog().getPrintRequestBody()) {
            //处理JSON或其他请求体内容
            if (GuyuServletUtils.isJsonRequest(request.getContentType())) {
                reqBody = GuyuServletUtils.getRequestBody(request);
            }
        }
        //打印返回结果
        String result = "";
        if (webProperties.getRequestLog().getPrintResponseBody()) {
            result = GuyuServletUtils.getResponseBody(request, response);
        }
        log.info("[GUYU] end => url:[ {} ], cost:[ {} ms ], reqParam:[ {} ], reqBody:[ {} ], result:[ {} ]",
                url, cost, reqParam, reqBody, result);
        KEY_CACHE.remove();
    }

    /**
     * 是否满足打印日志
     */
    private boolean hasEnabled(HttpServletRequest request) {
        if (!webProperties.getRequestLog().getEnabled()) {
            return false;
        }
        // 排除请求
        return !webProperties.getRequestLog().getExcludeUrl().contains(request.getRequestURI());
    }

}
